1   // Copyright 2010, 2011 The Apache Software Foundation
2   //
3   // Licensed under the Apache License, Version 2.0 (the "License");
4   // you may not use this file except in compliance with the License.
5   // You may obtain a copy of the License at
6   //
7   // http://www.apache.org/licenses/LICENSE-2.0
8   //
9   // Unless required by applicable law or agreed to in writing, software
10  // distributed under the License is distributed on an "AS IS" BASIS,
11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  // See the License for the specific language governing permissions and
13  // limitations under the License.
14  
15  package org.apache.tapestry5.func;
16  
17  import java.util.Arrays;
18  import java.util.Collections;
19  import java.util.Comparator;
20  import java.util.Iterator;
21  import java.util.List;
22  import java.util.Locale;
23  
24  import org.testng.annotations.Test;
25  
26  public class FuncTest extends BaseFuncTest
27  {
28  
29      @Test
30      public void flow_reverse()
31      {
32          assertFlowValues(F.flow(1, 2, 3).reverse(), 3, 2, 1);
33      }
34  
35      @Test
36      public void combine_mappers()
37      {
38          List<Boolean> even = F.flow("Mary", "had", "a", "little", "lamb").map(F.combine(stringToLength, toEven))
39                  .toList();
40  
41          assertListsEquals(even, true, false, false, true, true);
42      }
43  
44      @Test
45      public void map_empty_collection_is_the_empty_list()
46      {
47          List<String> source = Arrays.asList();
48  
49          List<Integer> lengths = F.flow(source).map(stringToLength).toList();
50  
51          assertSame(lengths, Collections.EMPTY_LIST);
52      }
53  
54      @Test
55      public void each()
56      {
57          List<String> source = Arrays.asList("Mary", "had", "a", "little", "lamb");
58  
59          final StringBuffer buffer = new StringBuffer();
60  
61          Worker<String> worker = new Worker<String>()
62          {
63              @Override
64              public void work(String value)
65              {
66                  if (buffer.length() > 0)
67                      buffer.append(' ');
68  
69                  buffer.append(value);
70              }
71          };
72  
73          F.flow(source).each(worker);
74  
75          assertEquals(buffer.toString(), "Mary had a little lamb");
76      }
77  
78      @Test
79      public void each_on_non_array_flow()
80      {
81          List<String> source = Arrays.asList("Mary", "had", "a", "little", "lamb");
82  
83          final StringBuffer buffer = new StringBuffer();
84  
85          Worker<String> worker = new Worker<String>()
86          {
87              @Override
88              public void work(String value)
89              {
90                  if (buffer.length() > 0)
91                      buffer.append(' ');
92  
93                  buffer.append(value);
94              }
95          };
96  
97          F.flow(source).filter(new Predicate<String>()
98          {
99              @Override
100             public boolean accept(String object)
101             {
102                 return object.contains("a");
103             }
104         }).each(worker);
105 
106         assertEquals(buffer.toString(), "Mary had a lamb");
107     }
108 
109     @Test
110     public void flow_each()
111     {
112         Flow<String> flow = F.flow("Mary", "had", "a", "little", "lamb");
113 
114         final StringBuffer buffer = new StringBuffer();
115 
116         Worker<String> worker = new Worker<String>()
117         {
118             @Override
119             public void work(String value)
120             {
121                 if (buffer.length() > 0)
122                     buffer.append(' ');
123 
124                 buffer.append(value);
125             }
126         };
127 
128         assertSame(flow.each(worker), flow);
129 
130         assertEquals(buffer.toString(), "Mary had a little lamb");
131     }
132 
133     @Test
134     public void combine_workers()
135     {
136         final StringBuffer buffer = new StringBuffer();
137 
138         Worker<String> appendWorker = new Worker<String>()
139         {
140             @Override
141             public void work(String value)
142             {
143                 if (buffer.length() > 0)
144                     buffer.append(' ');
145 
146                 buffer.append(value);
147             }
148         };
149 
150         Worker<String> appendLength = new Worker<String>()
151         {
152             @Override
153             public void work(String value)
154             {
155                 buffer.append('(');
156                 buffer.append(value.length());
157                 buffer.append(')');
158             }
159         };
160 
161         F.flow("Mary", "had", "a", "little", "lamb").each(F.combine(appendWorker, appendLength));
162 
163         assertEquals(buffer.toString(), "Mary(4) had(3) a(1) little(6) lamb(4)");
164     }
165 
166     @Test
167     public void filter()
168     {
169         List<Integer> input = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
170 
171         List<Integer> output = F.flow(input).filter(evenp).toList();
172 
173         assertListsEquals(output, 2, 4, 6);
174     }
175 
176     @Test
177     public void flow_filter()
178     {
179         assertFlowValues(F.flow(1, 2, 3, 4, 5, 6, 7).filter(evenp), 2, 4, 6);
180     }
181 
182     @Test
183     public void remove()
184     {
185         List<Integer> input = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
186 
187         List<Integer> output = F.flow(input).remove(evenp).toList();
188 
189         assertListsEquals(output, 1, 3, 5, 7);
190     }
191 
192     @Test
193     public void flow_remove()
194     {
195         List<Integer> output = F.flow(1, 2, 3, 4, 5, 6, 7).remove(evenp).toList();
196 
197         assertListsEquals(output, 1, 3, 5, 7);
198     }
199 
200     @Test
201     public void filter_empty_is_the_empty_list()
202     {
203         List<Integer> input = Arrays.asList();
204 
205         List<Integer> output = F.flow(input).filter(evenp).toList();
206 
207         assertSame(output, Collections.EMPTY_LIST);
208     }
209 
210     @Test
211     public void combine_predicate_with_and()
212     {
213         List<Integer> input = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
214 
215         List<Integer> output = F.flow(input).filter(F.and(F.gt(2), F.lt(5))).toList();
216 
217         assertListsEquals(output, 3, 4);
218     }
219 
220     @Test
221     public void combine_predicate_with_or()
222     {
223         List<Integer> input = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
224 
225         List<Integer> output = F.flow(input).filter(F.or(F.lt(3), F.gt(5))).toList();
226 
227         assertListsEquals(output, 1, 2, 6, 7);
228     }
229 
230     @Test
231     public void eql_predicate()
232     {
233         List<Integer> input = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
234 
235         List<Integer> output = F.flow(input).filter(F.eql(4)).toList();
236 
237         assertListsEquals(output, 4);
238     }
239 
240     @Test
241     public void numeric_comparison()
242     {
243         List<Integer> input = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
244 
245         assertEquals(F.flow(input).filter(F.eq(3)).toList(), Arrays.asList(3));
246         assertEquals(F.flow(input).filter(F.neq(3)).toList(), Arrays.asList(1, 2, 4, 5, 6, 7));
247         assertEquals(F.flow(input).filter(F.lt(3)).toList(), Arrays.asList(1, 2));
248         assertEquals(F.flow(input).filter(F.lteq(3)).toList(), Arrays.asList(1, 2, 3));
249         assertEquals(F.flow(input).filter(F.gteq(3)).toList(), Arrays.asList(3, 4, 5, 6, 7));
250     }
251 
252     @Test
253     public void select_and_filter()
254     {
255         Predicate<String> combinedp = F.toPredicate(F.combine(stringToLength, toEven));
256 
257         Mapper<String, String> identity = F.identity();
258         Predicate<String> isNull = F.isNull();
259 
260         // Converting to null and then filtering out nulls is the hard way to do filter or remove,
261         // but exercises the code we want to test.
262 
263         List<String> filtered = F.flow("Mary", "had", "a", "little", "lamb").map(F.select(combinedp, identity))
264                 .remove(isNull).toList();
265 
266         assertListsEquals(filtered, "Mary", "little", "lamb");
267     }
268 
269     @Test
270     public void null_and_not_null()
271     {
272         Predicate<String> isNull = F.isNull();
273         Predicate<String> isNotNull = F.notNull();
274 
275         assertEquals(isNull.accept(null), true);
276         assertEquals(isNotNull.accept(null), false);
277 
278         assertEquals(isNull.accept("foo"), false);
279         assertEquals(isNotNull.accept("bar"), true);
280     }
281 
282     @Test
283     public void array_flow_reduce()
284     {
285         int total = F.flow(F.flow("Mary", "had", "a", "little", "lamb").map(stringToLength).toList()).reduce(
286                 F.SUM_INTS, 0);
287 
288         assertEquals(total, 18);
289     }
290 
291     @Test
292     public void general_flow_reduce()
293     {
294         int total = F.flow("Mary", "had", "a", "little", "lamb").map(stringToLength).reduce(F.SUM_INTS, 0);
295 
296         assertEquals(total, 18);
297     }
298 
299     @Test
300     public void reverse_a_short_list_is_same_object()
301     {
302         Flow<Integer> empty = F.flow();
303 
304         assertSame(empty.reverse(), empty);
305 
306         Flow<Integer> one = F.flow(1);
307 
308         assertSame(one.reverse(), one);
309     }
310 
311     @Test
312     public void concat_flows()
313     {
314         Flow<Integer> first = F.flow(1, 2, 3);
315 
316         Flow<Integer> updated = first.concat(F.flow(4, 5, 6));
317 
318         assertFlowValues(updated, 1, 2, 3, 4, 5, 6);
319     }
320 
321     @Test
322     public void concat_onto_empty_list()
323     {
324         Flow<Integer> empty = F.flow();
325         Flow<Integer> flow = F.flow(1, 2, 3);
326 
327         assertSame(empty.concat(flow), flow);
328     }
329 
330     @Test
331     public void concat_list_onto_flow()
332     {
333         Flow<Integer> first = F.flow(1, 2, 3);
334 
335         Flow<Integer> updated = first.concat(Arrays.asList(4, 5, 6));
336 
337         assertFlowValues(updated, 1, 2, 3, 4, 5, 6);
338     }
339 
340     @Test
341     public void append_values_onto_flow()
342     {
343         Flow<Integer> first = F.flow(1, 2, 3);
344 
345         Flow<Integer> updated = first.append(4, 5, 6);
346 
347         assertFlowValues(updated, 1, 2, 3, 4, 5, 6);
348     }
349 
350     @Test
351     public void sort_comparable_list()
352     {
353         assertFlowValues(F.flow("fred", "barney", "wilma", "betty").sort(), "barney", "betty", "fred", "wilma");
354     }
355 
356     @Test
357     public void sort_a_short_list_returns_same()
358     {
359         Flow<String> zero = F.flow();
360 
361         Comparator<String> comparator = new Comparator<String>()
362         {
363             @Override
364             public int compare(String o1, String o2)
365             {
366                 return o1.length() - o2.length();
367             }
368         };
369 
370         assertSame(zero.sort(), zero);
371         assertSame(zero.sort(comparator), zero);
372 
373         Flow<String> one = F.flow("Hello");
374 
375         assertSame(one.sort(), one);
376         assertSame(one.sort(comparator), one);
377     }
378 
379     @Test
380     public void sort_using_explicit_comparator()
381     {
382         Flow<String> flow = F.flow("a", "eeeee", "ccc", "bb", "dddd");
383         Comparator<String> comparator = new Comparator<String>()
384         {
385             @Override
386             public int compare(String o1, String o2)
387             {
388                 return o1.length() - o2.length();
389             }
390         };
391 
392         assertFlowValues(flow.sort(comparator), "a", "bb", "ccc", "dddd", "eeeee");
393     }
394 
395     @Test(expectedExceptions = ClassCastException.class)
396     public void unable_to_sort_a_flow_of_non_comparables()
397     {
398         Flow<Locale> flow = F.flow(Locale.ENGLISH, Locale.FRANCE);
399 
400         flow.sort();
401     }
402 
403     @Test
404     public void flows_are_iterable()
405     {
406         Flow<Integer> flow = F.flow(1, 3, 5, 7);
407 
408         int total = 0;
409 
410         for (int i : flow)
411         {
412             total += i;
413         }
414 
415         assertEquals(total, 16);
416     }
417 
418     @Test
419     public void first_of_non_empty_flow()
420     {
421         assertEquals(F.flow("Mary", "had", "a", "little", "lamb").first(), "Mary");
422     }
423 
424     @Test
425     public void rest_of_non_empty_flow()
426     {
427         assertFlowValues(F.flow("Mary", "had", "a", "little", "lamb").rest(), "had", "a", "little", "lamb");
428     }
429 
430     @Test
431     public void flow_rest_is_cached()
432     {
433         Flow<Integer> flow = F.flow(1, 2, 3);
434 
435         assertSame(flow.rest(), flow.rest());
436     }
437 
438     @Test
439     public void first_of_empty_is_null()
440     {
441         assertNull(F.flow().first());
442     }
443 
444     @Test
445     public void rest_of_empty_is_still_empty_and_not_null()
446     {
447         assertTrue(F.flow().rest().isEmpty());
448     }
449 
450     @Test
451     public void list_of_empty_flow_is_empty()
452     {
453         assertTrue(filteredEmpty.isEmpty());
454         assertSame(filteredEmpty.toList(), Collections.EMPTY_LIST);
455     }
456 
457     @Test
458     public void operations_on_empty_list_yield_empty()
459     {
460         assertSame(filteredEmpty.reverse(), F.EMPTY_FLOW);
461         assertSame(filteredEmpty.sort(), F.EMPTY_FLOW);
462         assertSame(filteredEmpty.sort(new Comparator<Integer>()
463         {
464             @Override
465             public int compare(Integer o1, Integer o2)
466             {
467                 unreachable();
468 
469                 return 0;
470             }
471         }), F.EMPTY_FLOW);
472     }
473 
474     @Test
475     public void sort_non_array_flow()
476     {
477         assertFlowValues(filteredEmpty.append(7, 3, 9).sort(), 3, 7, 9);
478     }
479 
480     @Test
481     public void reverse_non_array_flow()
482     {
483         assertFlowValues(filteredEmpty.append(1, 2, 3).reverse(), 3, 2, 1);
484     }
485 
486     @Test(expectedExceptions = UnsupportedOperationException.class)
487     public void remove_on_flow_iterator_is_not_supported()
488     {
489         Flow<Integer> flow = F.flow(1, 2, 3).filter(evenp);
490 
491         Iterator<Integer> it = flow.iterator();
492 
493         assertTrue(it.hasNext());
494         assertEquals(it.next(), new Integer(2));
495 
496         it.remove();
497     }
498 
499     @Test
500     public void sort_with_comparator_on_non_array_flow()
501     {
502         Flow<String> flow = F.flow("Mary", "had", "a", "little", "lamb");
503 
504         List<String> result = flow.filter(new Predicate<String>()
505         {
506             @Override
507             public boolean accept(String object)
508             {
509                 return object.contains("a");
510             }
511         }).sort(new Comparator<String>()
512         {
513             @Override
514             public int compare(String o1, String o2)
515             {
516                 return o1.length() - o2.length();
517 
518             };
519         }).toList();
520 
521         assertListsEquals(result, "a", "had", "Mary", "lamb");
522     }
523 
524     @Test
525     public void each_on_empty_flow()
526     {
527         Flow<Integer> flow = F.emptyFlow();
528 
529         assertSame(flow.each(new Worker<Integer>()
530         {
531             @Override
532             public void work(Integer value)
533             {
534                 unreachable();
535             }
536         }), flow);
537     }
538 
539     @Test
540     public void remove_on_empty_flow()
541     {
542         Flow<Integer> flow = F.emptyFlow();
543 
544         assertSame(flow.remove(evenp), flow);
545     }
546 
547     @Test
548     public void reduce_on_empty_flow()
549     {
550         Flow<Integer> flow = F.emptyFlow();
551         Integer initial = 99;
552 
553         assertSame(flow.reduce(new Reducer<Integer, Integer>()
554         {
555             @Override
556             public Integer reduce(Integer accumulator, Integer value)
557             {
558                 unreachable();
559 
560                 return null;
561             }
562         }, initial), initial);
563     }
564 
565     @Test
566     public void count_of_the_empty_flow_is_zero()
567     {
568         assertEquals(F.flow().count(), 0);
569     }
570 
571     @Test
572     public void count_of_array_flow()
573     {
574         assertEquals(F.flow(1, 2, 3).count(), 3);
575     }
576 
577     @Test
578     public void count_of_a_filtered_flow()
579     {
580         Flow<String> flow = F.flow("Mary", "had", "a", "little", "lamb");
581 
582         assertEquals(flow.filter(F.isNull()).count(), 0);
583         assertEquals(flow.removeNulls().count(), 5);
584     }
585 
586     @Test
587     public void count_of_a_large_flow()
588     {
589         Flow<Integer> flow = F.series(1, 1).take(50000);
590 
591         assertEquals(flow.count(), 50000);
592     }
593 
594     @Test
595     public void concat_empty_list()
596     {
597         Flow<Integer> flow = F.flow(1, 3);
598 
599         assertFlowValues(flow.concat(flow.filter(evenp)), 1, 3);
600     }
601 
602     @Test
603     public void to_array()
604     {
605         Flow<Integer> flow = F.range(1, 10).drop(2).take(3);
606 
607         assertTrue(Arrays.equals(flow.toArray(Integer.class), new Integer[]
608         { 3, 4, 5 }));
609     }
610 
611     @Test
612     public void lazy_flow_from_iterable()
613     {
614         Iterable<Integer> iterable = new Iterable<Integer>()
615         {
616 
617             @Override
618             public Iterator<Integer> iterator()
619             {
620                 return Arrays.asList(9, 7, 1).iterator();
621             }
622         };
623 
624         Flow<Integer> flow = F.flow(iterable);
625 
626         assertFlowValues(flow, 9, 7, 1);
627     }
628 }